﻿/********************************************************************************/
/* 	0724th - state.d															*/
/*------------------------------------------------------------------------------*/
/*	製作		（　゜ワ゜）ノ　／　松久貫太									*/
/*	製作開始　	2007/05/11														*/
/*	MAIL		omega@personal.email.ne.jp										*/
/*	URL		http://nagoya.cool.ne.jp/o_mega										*/
/*																				*/
/*	このソースは「やらわかライセンス」の元で配布されています。					*/
/*-更新履歴---------------------------------------------------------------------*/
/*	2007/--/--																	*/
/*-その他-----------------------------------------------------------------------*/
/*	なし																		*/
/********************************************************************************/

/* ライブラリのインポート *******************************************************/
private import hell2;		// dHell2ライブラリ
private import screen;
private import player;
private import shot;
private import vector;
private import effect;
private import keypad;

private import std.string;
private import std.math;
private import std.math2;
private import std.stream;

/* グローバル定数定義 ***********************************************************/
GameState g_gamestate = null;


/* load *************************************************************************/
/*	リソースの読み込み															*/
/*-引数-------------------------------------------------------------------------*/
/*	なし																		*/
/*-返り値-----------------------------------------------------------------------*/
/*	なし																		*/
/********************************************************************************/
void load()
{
	Hell_loadTexture("font","resource/font/font.bmp" , [255,255,255]);
	
	Hell_write("resource loaded.\n");
}

/* GameState ********************************************************************/
/*	ゲーム全体の状態遷移を管理するクラス										*/
/********************************************************************************/
class GameState
{
private:
	int msg;				// リクエストメッセージ
public:
	enum
	{
		MSG_NONE,
		MSG_REQ_TITLE,			// タイトル状態へ　行きたい
		MSG_REQ_GAME_ORIGINAL,		// ゲーム
		MSG_REQ_GAME_ARRANGE,		// ゲーム
//		MSG_REQ_GAME_SEQUENTIAL,	// ゲーム
	}
	
	void move(){}
	void draw(){}
	
	// 設定
	void setMsg(int m)
	{
		msg = m;
	}
	// 取得
	int getMsg()
	{
		return msg;
	}
}



void loop()
{
	if(g_gamestate)
	{
		// メッセージ指示による状態遷移
		switch(g_gamestate.msg)
		{
			case GameState.MSG_NONE:
				break;
			case GameState.MSG_REQ_TITLE:
				g_gamestate = new TitleMain();
				break;
			case GameState.MSG_REQ_GAME_ORIGINAL:
				g_gamestate = new GameMain(GameMain.RULE.ORIGINAL);
				break;
			case GameState.MSG_REQ_GAME_ARRANGE:
				g_gamestate = new GameMain(GameMain.RULE.ARRANGE);
				break;
/*
			case GameState.MSG_REQ_GAME_SEQUENTIAL:
				g_gamestate = new GameMain(GameMain.RULE.SEQUENTIAL);
				break;
*/
			default:
				Hell_write("Uknown msg at loop.");
		}
	}
	else
	{
		// 初期状態
		g_gamestate = new TitleMain();
		Hell_write("Exec loop.\n");
	}
	
	g_gamestate.move();
	g_gamestate.draw();
}

/* GameMain *********************************************************************/
/*	ゲーム本体の状態															*/
/********************************************************************************/
class TitleMain : GameState
{
public:
	int timer;
	static int rule = 0;
	
	this()
	{
		timer = 0;
		//rule = 0;
	}
	
	void move()
	{
		timer++;
		if(timer > 5 && isPushEnter())
		{
			if(rule == GameMain.RULE.ORIGINAL)		setMsg(GameState.MSG_REQ_GAME_ORIGINAL);
			if(rule == GameMain.RULE.ARRANGE)		setMsg(GameState.MSG_REQ_GAME_ARRANGE);
		//	if(rule == GameMain.RULE.SEQUENTIAL)	setMsg(GameState.MSG_REQ_GAME_SEQUENTIAL);
		}
		
		if(isPushUp() || isPushLeft()) rule--;
		if(isPushDown() || isPushRight()) rule++;
		rule = (rule + GameMain.RULE.LAST)% GameMain.RULE.LAST;
	}
	
	void draw()
	{
		Hell_begin();
		Hell_setAlpha(HELL_ALPHA_ADD);
		setPerspective();
		
		{
			glLoadIdentity();
			glTranslatef(0,0,-10);
			glRotatef(timer / 0.2 , -timer / 0.3 , timer / 15.0);
			
			glScalef(0.8, 0.8, 0.8);
			glColor4f(0.1, 1.0, 0.4, 0.3);
			BulletShape.drawPolygon();
			glColor4f(0.5, 1.0, 0.75, 0.9);
			BulletShape.drawWire();
		}
		
		{
			glLoadIdentity();
			glTranslatef(0,0,-10);
			glRotatef(-timer / 0.5 ,timer / 0.3 , timer / 15.0);
			
			glScalef(2.0 ,2.0, 2.0);
			glColor4f(0.1 ,1.0 ,0.4 ,0.7);
			BulletShape.drawWire();
		}
		
		{
			glLoadIdentity();
			glTranslatef(0,0,-10);
			glRotatef(-timer / 1.3 ,-timer / 15.0 , timer / 1.7);
			
			glScalef(4.0 ,4.0, 4.0);
			glColor4f(0.1 ,1.0 ,0.4 ,0.3);
			BulletShape.drawWire();
		}
		
		resetPerspective();
		Hell_setAlpha(HELL_ALPHA_NORMAL);
		
		Hell_drawFont("Small Slow 3D",120 ,120 ,1.0 );
		Hell_drawFont("GameHell2000 / OMEGA 2007" , 120, 480-48 , 0.5 , 160,160,160);
		Hell_drawFont(" Original Game by CHAIN",120 ,480-24 ,0.5 , 160,160,160);
		
		Hell_drawFont(GameMain.rulename[rule],240 ,240 ,0.5 , 24,255,128);
		if(timer % 60 < 50)
		{
			Hell_drawFont("Push space",240 ,240 + 24 ,0.5 );
		}
	}
}

/* GameMain *********************************************************************/
/*	ゲーム本体の状態															*/
/********************************************************************************/
class GameMain : GameState
{
public:
	Player player = null;
	ShotActor shotactor = null;
	EffectActor effectactor = null;
	int timer;
	int level;
	int level_timer;
	int score;
	
	int gameover_timer;
	
	float back_rx , back_ry , back_rz;
	
	enum RULE
	{
		ORIGINAL,
		ARRANGE,
		//SEQUENTIAL,
		LAST,
	}
	static char[][] rulename = [" Original"," Arrange","Sequential"];
	
	RULE rule;
	
	
	this(RULE rl)
	{
		player = new Player(this);
		shotactor = new ShotActor(this,4096);
		effectactor = new EffectActor(256);
		timer = 0;
		score = 0;
		level = 0;
		level_timer = 0;
		gameover_timer = 0;
		
		rule = rl;
		
		back_rx = Hell_randInt(-10,10) / 3.0;
		back_ry = Hell_randInt(-10,10) / 3.0;
		back_rz = Hell_randInt(-10,10) / 10.0;
		if((Hell_randInt(0,5) < 2 && rule == RULE.ORIGINAL) || (Hell_randInt(0,5) < 4 && rule == RULE.ARRANGE))
		{
			back_rx /= 4;
			back_ry /= 4;
		}
	}
	
	void move()
	{
		timer++;
		
		if(player.exist)
		{
			shotactor.move();
			effectactor.move();
			player.move();
			
			score++;
			
			generateBullets();
		}
		else
		{
			gameover_timer++;
			effectactor.move();
			
			if(isPushEnter())
			{
				setMsg(GameState.MSG_REQ_TITLE);
			}
		}
	}
	
	void draw()
	{
		Hell_begin();
		setPerspective();
		
		Hell_setAlpha(HELL_ALPHA_ENHANCE);
		drawBack();
		Hell_setAlpha(HELL_ALPHA_ADD);
		
		drawCharacters();
		drawConsole();
	}
	
	void drawBack()
	{
		switch(rule)
		{
			case RULE.ORIGINAL:
				for(int t=0;t<128;t++)
				{
					if(t % 4 != 0) continue;
					float f = (timer + t) / 10.0;
					glLoadIdentity();
					glTranslatef(0,0,-10);
					glScalef(10.0 ,10.0, 10.0);
					glRotatef(f * back_rx ,f * back_ry , f * back_rz);
					glColor4f(0.05 ,0.1 ,1.0 ,  0.15 * (t+1) / 128.0);
					CubeShape.drawWire();
				}
				break;
				
			case RULE.ARRANGE:
				for(int t=0;t<32;t++)
				{
					float z = ((timer % 20) + t * 20 - 100) / 10.0;
					glLoadIdentity();
					glTranslatef(back_ry / 8 * sin(score / 100.0) * z, back_rx / 8 * sin(score / 197.0) * z,-z);
					glScalef(2.0 ,2.0, 10.0);
					glRotatef(0 ,0 , z * back_rz * score * 0.01);
					glColor4f(0.05 ,0.1 ,1.0 ,  0.3 * (32 - t) / 32.0);
					HexShape.drawWire();
				}
				for(int t=0;t<32;t++)
				{
					float z = ((20 - timer % 20) + t * 20 - 100) / 10.0;
					glLoadIdentity();
					glTranslatef(back_rx / 4 * sin(score / 70.0) * z, back_ry / 4 * sin(score / 59.0) * z,-z);
					glScalef(5.0 ,5.0, 10.0);
					glRotatef(0 ,0 , -z * back_rz * score * 0.02);
					glColor4f(0.05 ,0.1 ,1.0 ,  0.15 * (32 - t) / 32.0);
					HexShape.drawWire();
				}
				break;
			default:
				break;
		}
	}
	void drawCharacters()
	{
		setPerspective();
		Hell_setAlpha(HELL_ALPHA_ADD);
		
		shotactor.draw();
		player.draw();
		effectactor.draw();
	}
	
	void drawConsole()
	{
		resetPerspective();
		Hell_setAlpha(HELL_ALPHA_NORMAL);
		
		player.drawStatus();
		//Hell_drawFont(std.string.toString(cast(int)timer),0 ,0 ,0.5 );
		Hell_drawFont("Level:" ~ std.string.toString(cast(int)level),0 ,0 ,0.5 );
		Hell_drawFont("Score:" ~ std.string.toString(cast(int)score),0 ,24 ,0.5 );
		
		if(!player.exist)
		{
			Hell_drawFont("GAME OVER",180 ,240 - 24 ,1.0 , 255,24,24,255);
			
			Hell_setAlpha(HELL_ALPHA_REVERSE);
			resetPerspective();
			Hell_drawRect(0,240 - 32 ,640,64,0,0, 255,24,24);
			setPerspective();
		}
	}
	
	void generateBullets()
	{
		if(timer % 180 == 30)
		{
			int difc = level + 1;
			for(int t=0;t<3 + difc;t++)
			{
				int flag = (Hell_randInt(0,999) / 10) % 4;
				Vec3 p = new Vec3();
				Vec3 v = new Vec3();
				switch(flag)
				{
					case 0:		// 左の壁
						p.x = -20.0;
						p.y = (Hell_randInt(-100,100) / 5.0);
						break;
					case 1:		// 右の壁
						p.x = 20.0;	
						p.y = (Hell_randInt(-100,100) / 5.0);
						break;
					case 2:		// 上
						p.x = (Hell_randInt(-100,100) / 5.0);
						p.y = -20.0;
						break;
					case 3:		// 下
						p.x = (Hell_randInt(-100,100) / 5.0);
						p.y = 20.0;
						break; 
					default:
						break;
				}
				
				int minsp = 100 - difc * 5;
				int maxsp = 100 + difc * 3;
				if(minsp < 10)
				{
					minsp = 10;
				}
				v.toVector2D(
					Hell_randInt(minsp , maxsp) / 1000.0 ,
					p.atan2D(player.position) + Hell_randInt(-(difc % 5) * 7,(difc % 5) * 7) / 100.0);
				shotactor.fire(p,v, SHOTTYPE.NORMAL, SHOTCOLOR.WHITE);
			}
			level++;
		}
		
	}
}
